# Package importation
import os
import geopandas as gpd
import pandas as pd
import numpy as np
import panel as pn
pn.extension('tabulator')
import xarray as xr
import cufflinks as cf
from colour import Color
import matplotlib.pyplot as plt
import plotly
import plotly.express as px
from plotly import __version__
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
#Interactive plot packages
import holoviews as hv
import hvplot.xarray
import hvplot.pandas
hv.extension('bokeh', width=90)
import geoviews as gv
import geoviews.feature as gf
from geoviews import dim
from geoviews import opts
from geoviews.tile_sources import EsriImagery
import cartopy
import cartopy.feature as cpf
import cartopy.crs as ccrs
#SQL packages
from sqlalchemy import create_engine
from sqlalchemy import inspect
from matplotlib_scalebar.scalebar import ScaleBar
%matplotlib inline
%load_ext sql
The sql extension is already loaded. To reload it, use: %reload_ext sql
# For offline use
cf.go_offline()
#cf.set_config_file(offline=False, world_readable=True)
#creates the connection between the notebook and our SQL server
host = "localhost"
database = "Fires"
user = os.getenv('PSQL_USER')
password = os.getenv('PSQL_PASSWORD')
connection_string = f"postgresql://{user}:{password}@{host}/{database}"
engine = create_engine(connection_string)
#import data from database
Study_area = gpd.read_postgis('SELECT * FROM landcover.departments', con=engine)
PACA_limits = gpd.read_postgis('SELECT * FROM landcover.lines', con=engine)
#plot the data
Study_area_map = Study_area.plot('nom', legend = True, legend_kwds =
{'loc': 'lower right', 'fontsize' : '15',
'title' : 'Study Area', 'title_fontsize' : '15'},
cmap = 'rainbow', figsize=(20,15))
#addition of scalebar
echelle = ScaleBar(
dx=1, label='Scale',
location='lower left', # in relation to the whole plot
label_loc='left', scale_loc='bottom' # in relation to the line
)
Study_area_map.add_artist(echelle)
#addition of north arrow
x, y, arrow_length = 0.075, 0.925, 0.075
Study_area_map.annotate('N', xy=(x, y), xytext=(x, y-arrow_length),
arrowprops=dict(facecolor='black', width=10, headwidth=20),
ha='center', va='center', fontsize=20,
xycoords=Study_area_map.transAxes)
Text(0.075, 0.8500000000000001, 'N')
Here we see the spread and intensity of forest fires in our area of study, futher comments can be found in the attached report.
#import data from database
feu = gpd.read_postgis('SELECT * FROM feu.feu', con=engine)
#plot the data
fig1, ax = plt.subplots(figsize=(20,15),)
limit_map = PACA_limits.plot('nom', color = 'k', figsize=(20,15), ax=ax)
feu_map = feu.plot('remark', legend = True, legend_kwds =
{'loc': 'lower right', 'fontsize' : '15',
'title' : 'Feu', 'title_fontsize' : '15'},
figsize=(20,15), cmap = 'Reds',ax=ax)
#addition of scalebar
echelle = ScaleBar(
dx=1, label='Scale',
location='lower left', # in relation to the whole plot
label_loc='left', scale_loc='bottom' # in relation to the line
)
feu_map.add_artist(echelle)
#addition of north arrow
x, y, arrow_length = 0.075, 0.925, 0.075
feu_map.annotate('N', xy=(x, y), xytext=(x, y-arrow_length),
arrowprops=dict(facecolor='black', width=10, headwidth=20),
ha='center', va='center', fontsize=20,
xycoords=feu_map.transAxes)
C:\Users\King\anaconda3\envs\geo_env\lib\site-packages\geopandas\plotting.py:641: UserWarning: Only specify one of 'column' or 'color'. Using 'color'.
Text(0.075, 0.8500000000000001, 'N')
Here we see the different forest types in our area of study, futher comments on the relationship between forest fires and forest types can be found in the attached report.
#import data from database
forest = gpd.read_postgis('SELECT * FROM landcover.forest_clip', con=engine)
#plot the data
fig2, ax = plt.subplots(figsize=(20,15),)
limit_map = PACA_limits.plot('nom', color = 'k', figsize=(20,15), ax=ax)
forest_map = forest.plot('remark', legend = True, legend_kwds =
{'loc': 'lower right', 'fontsize' : '15',
'title' : 'L’occupation du sol', 'title_fontsize' : '15'},
figsize=(20,15), cmap = 'Greens', ax = ax)
#addition of scalebar
scale = ScaleBar(
dx=1, label='Scale',
location='lower left', # in relation to the whole plot
label_loc='left', scale_loc='bottom' # in relation to the line
)
forest_map.add_artist(scale)
#addition of north arrow
x, y, arrow_length = 0.075, 0.925, 0.075
forest_map.annotate('N', xy=(x, y), xytext=(x, y-arrow_length),
arrowprops=dict(facecolor='black', width=10, headwidth=20),
ha='center', va='center', fontsize=20,
xycoords=forest_map.transAxes)
C:\Users\King\anaconda3\envs\geo_env\lib\site-packages\geopandas\plotting.py:641: UserWarning: Only specify one of 'column' or 'color'. Using 'color'.
Text(0.075, 0.8500000000000001, 'N')
Here we see the different agricultural activities in our area of study, futher comments on the relationship between forest fires and agricultural activities can be found in the attached report.
#import data from database
agricole = gpd.read_postgis('SELECT * FROM landcover.agricole_clip', con=engine)
#plot the data
fig3, ax = plt.subplots(figsize=(20,15),)
limit_map = PACA_limits.plot('nom', color = 'k', figsize=(20,15), ax=ax)
agricole_map = agricole.plot('remark', legend = True, legend_kwds =
{'loc': 'lower right', 'fontsize' : '15',
'title' : 'L’occupation du sol', 'title_fontsize' : '15'},
figsize=(20,15), cmap = 'jet', ax = ax)
#addition of scalebar
scale = ScaleBar(
dx=1, label='Scale',
location='lower left', # in relation to the whole plot
label_loc='left', scale_loc='bottom' # in relation to the line
)
agricole_map.add_artist(scale)
#addition of north arrow
x, y, arrow_length = 0.075, 0.925, 0.075
agricole_map.annotate('N', xy=(x, y), xytext=(x, y-arrow_length),
arrowprops=dict(facecolor='black', width=10, headwidth=20),
ha='center', va='center', fontsize=20,
xycoords=agricole_map.transAxes)
C:\Users\King\anaconda3\envs\geo_env\lib\site-packages\geopandas\plotting.py:641: UserWarning: Only specify one of 'column' or 'color'. Using 'color'.
Text(0.075, 0.8500000000000001, 'N')
Here we see the different climate zones in our area of study, futher comments on the relationship between forest fires and climate can be found in the attached report.
#import data from database
climate = gpd.read_postgis('SELECT * FROM climat.climat_paca', con=engine)
#plot the data
fig4, ax = plt.subplots(figsize=(20,15),)
limit_map = PACA_limits.plot('nom', color = 'k', figsize=(20,15), ax=ax)
climate_map = climate.plot('type', legend = True, legend_kwds =
{'loc': 'lower right', 'fontsize' : '15',
'title' : 'climate type', 'title_fontsize' : '15'},
figsize=(20,15), cmap = 'terrain',ax = ax)
#addition of scalebar
scale = ScaleBar(
dx=1, label='Scale',
location='lower left', # in relation to the whole plot
label_loc='left', scale_loc='bottom' # in relation to the line
)
climate_map.add_artist(scale)
#addition of north arrow
x, y, arrow_length = 0.075, 0.925, 0.075
climate_map.annotate('N', xy=(x, y), xytext=(x, y-arrow_length),
arrowprops=dict(facecolor='black', width=10, headwidth=20),
ha='center', va='center', fontsize=20,
xycoords=climate_map.transAxes)
C:\Users\King\anaconda3\envs\geo_env\lib\site-packages\geopandas\plotting.py:641: UserWarning: Only specify one of 'column' or 'color'. Using 'color'.
Text(0.075, 0.8500000000000001, 'N')
Here we see the urban zones in our area of study, futher comments on the relationship between forest fires and urban areas can be found in the attached report.
#import data from database
urbain = gpd.read_postgis('SELECT * FROM landcover.urbain_clip', con=engine)
#plot the data
fig5, ax = plt.subplots(figsize=(20,15),)
limit_map = PACA_limits.plot('nom', color = 'k', figsize=(20,15), ax=ax)
urbain_map = urbain.plot('remark', legend = True, legend_kwds =
{'loc': 'lower right', 'fontsize' : '15',
'title' : 'Zone Urbain', 'title_fontsize' : '15'},
figsize=(20,15), cmap = 'hsv',ax=ax)
#addition of scalebar
echelle = ScaleBar(
dx=1, label='Scale',
location='lower left', # in relation to the whole plot
label_loc='left', scale_loc='bottom' # in relation to the line
)
urbain_map.add_artist(echelle)
#addition of north arrow
x, y, arrow_length = 0.075, 0.925, 0.075
urbain_map.annotate('N', xy=(x, y), xytext=(x, y-arrow_length),
arrowprops=dict(facecolor='black', width=10, headwidth=20),
ha='center', va='center', fontsize=20,
xycoords=urbain_map.transAxes)
C:\Users\King\anaconda3\envs\geo_env\lib\site-packages\geopandas\plotting.py:641: UserWarning: Only specify one of 'column' or 'color'. Using 'color'.
Text(0.075, 0.8500000000000001, 'N')
The line plot below shows the evolution of the number of forest fires observed in the study area.
Données_promethées = pd.read_sql('SELECT * FROM graphs.incendies', engine)
nombre_incendies = Données_promethées[['années','nbr']].iplot(
x= 'années', y='nbr',filename='Données_promethées', kind='line', color="red", legend = True, title='Number of forest fires per year')
The bar chart below shows the evolution of surface area of forest fires observed in the study area between 1980 and 2022.
Données_promethées = pd.read_sql('SELECT * FROM graphs.incendies', engine)
surf_incendies = px.bar(Données_promethées, y= ['surf_ha' ], x = 'années', title='Total burnt surface per year')
surf_incendies.show()
The pie plot below shows the proportion of different sources of forest fires observed in the study area.
Time_of_fire = pd.read_sql('SELECT * FROM feu.graph', engine)
fig = px.pie(Time_of_fire, values='hours', names='remark', title='Source of forest fires')
fig.show()
The pie plot below shows the distribution of forest fires in term of month and department.
fig = px.scatter(Time_of_fire, x="months", y="department",
color="month", size="surf_ha",
hover_name="department", size_max=60, title='Forest fires by month and department')
fig.show()
#import data from database
feu = pd.read_sql('SELECT * FROM feu.graph', engine)
#make data interactive
feu = feu.interactive()
#create year slider
year_slider = pn.widgets.IntSlider(name = 'Year', start = 1981, end = 2022,step = 2, value = 1973 )
# Radio buttons for to select displayed
radio_button = pn.widgets.RadioButtonGroup(
name='Y axis',
options=['surf_ha', 'total_fires',],
button_type='success'
)
#Filter by remark column
remark_filter = ['remark', 'involontaire_particulier', 'involontaire_travaux', 'accidentelle', 'foudre', 'autres', 'malveillance']
# create data pipeline to link widgets and streamline dataset
data_pipeline1 = (
feu[(feu.Année <= year_slider) & (feu.remark.isin(remark_filter)) ]
.groupby(['department', 'Année'])[radio_button].mean()
.to_frame()
.reset_index()
.sort_values(by='Année')
.reset_index(drop=True)
)
#Create line plot
line_plot = data_pipeline1.hvplot(x = 'Année', by ='department', y = radio_button,line_width=2, title="Forest fires by department")
line_plot
# create data pipeline to link widgets and streamline dataset
data_pipeline2 = (
feu[
(feu.Année == year_slider) &
(feu.remark.isin(remark_filter))
]
.groupby(['Année', 'department'])[radio_button].sum()
.to_frame()
.reset_index()
.sort_values(by='Année')
.reset_index(drop=True)
)
#create bar chart
bar_plot = data_pipeline2.hvplot(kind='bar', x='department', y=radio_button, rot=35, height=400, width=500, title='Forest fires by department')
bar_plot
# create data pipeline to link widgets and streamline dataset
data_pipeline3 = (
feu[
(feu.Année == year_slider) &
(feu.remark.isin(remark_filter))
]
.groupby(['department'])[radio_button].sum()
.to_frame()
.reset_index()
.sort_values(by='department')
.reset_index(drop=True)
)
#create table plot
table_plot = data_pipeline3.pipe(pn.widgets.Tabulator, pagination='remote', page_size = 20, height=380, width=400, sizing_mode='stretch_width', )
table_plot
#import data from database
feu1 = gpd.read_postgis("SELECT geom, department, remark, années, remark_2, surface FROM feu.scatterplot where layer = 'feu_points'", engine)
limit1 = gpd.read_postgis("SELECT geom, department, remark, années, remark_2, surface FROM feu.scatterplot where layer != 'feu_points'", engine)
#extract long and lat, transformed to pandas dataframe
feu2 = pd.DataFrame({'Longitude': feu1.geometry.x, 'Latitude': feu1.geometry.y, 'Remark_2': feu1.remark_2, 'Remark':feu1.remark, 'Surface': feu1.surface, 'Department': feu1.department, 'Year': feu1.années})
limit2 = pd.DataFrame({'Longitude': limit1.geometry.x, 'Latitude': limit1.geometry.y, 'Remark_2': limit1.remark_2, 'Remark':limit1.remark, 'Surface': limit1.surface, 'Department': limit1.department, 'Year': limit1.années})
#make data interactive
#make data interactive
feu2 = feu2.interactive()
department_list = [feu2, 'Department']
scatterplot_pipeline = (
feu2[
(feu2.Year == year_slider) &
(~ (feu2.Department.isin([department_list])))
]
.groupby(['Department','Year', 'Longitude', 'Latitude'])['Surface'].sum()
.to_frame()
.reset_index()
.sort_values(by='Year')
.reset_index(drop=True)
)
scatterplot_pipeline
limit_plot = limit2.hvplot(x='Longitude',
y='Latitude',
size=0.01, kind="scatter",
alpha=0.7,color='black',
legend=False,
height=420,
width=500)
scatterplot = scatterplot_pipeline.hvplot(x='Longitude',
y='Latitude',
by='Department',
size=30, kind="scatter",
alpha=0.7,
legend=False,
height=420,
width=500)
scatterplot*limit_plot
Description1 = "### The objective of this study is to focus on the phenomenon of forest fires by putting the problem in the geographical context of southern eastern France (zone Prométhée)."
Description2 = "### The geospatial data analysis on the phenomenon of forest fires between 1973 and 2022 makes it possible to explore both the interannual variability in terms of the number and area of burned surfaces and the diversity of factors (anthropogenic and environmental inducing spatial disparities). It is important to note that these few data points cannot create a complete picture of the phenomenon of fires in the Provence-Alpes-Côte d'Azur region. However, the diversity of the environment, agricultural practices and calendars, the extension or regression of wooded areas according to demographic pressure and the mechanization of agriculture, and the conflict zones that have multiplied in recent years are all parameters to be integrated into the analysis as forest fires appear to be a polymorphic phenomena."
Dashboard_PACA = (
pn.Row( pn.Column(pn.pane.Markdown("# PACA forest fires dashboard"),
pn.pane.Markdown(Description1),
pn.pane.PNG('PACA1.png', sizing_mode='scale_both'),
pn.pane.Markdown(Description2)),
pn.Column(scatterplot * limit_plot,line_plot),
pn.Column(table_plot, bar_plot)
)
)
Dashboard_PACA.servable()
Dashboard_PACA.save('Dashboard_PACA.html', title = 'dashboard_embeded', embed = True)